package controller;

import interfaz.IRepresentacionesDeDiagrama;

import java.awt.Label;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import javax.swing.JOptionPane;


import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGeometry;

import constants.DiagramaConstants;

import utils.Mensaje;

import view.Pantalla;
import view.atributo.EditarAtributoCompuestoDialogo;
import view.atributo.AtributoDialogo;
import view.entidad.EditarEntidadDialogo;
import view.entidad.GlobalEntidadDialogo;
import view.entidad.NuevaEntidadDialogo;


import model.Atributo;
import model.AtributoCompuesto;
import model.Coordenada;
import model.Diagrama;
import model.Entidad;
import model.Proyecto;
import model.RepresentacionDeDiagrama;

public class ManagerEntidad implements IRepresentacionesDeDiagrama {
	
	private NuevaEntidadDialogo vistaNuevaEntidad;
	private GlobalEntidadDialogo vistaEntidadGlobal;
	private EditarEntidadDialogo vistaEditarEntidad;
	private EditarAtributoCompuestoDialogo vistaAtributoCompuesto;
	private Entidad modelEntidad;
	private Atributo modelAtributo;
	private AtributoCompuesto modelAtributoCompuesto;
	private Pantalla pantalla = Pantalla.getPantalla();
	private Proyecto proyecto;
	private Diagrama diagramaActual;
	private ManagerAreaDeTrabajo controladorAreaDeTrabajo = ManagerAreaDeTrabajo.getInstance();
	private ManagerAtributo controladorDeAtributo = new ManagerAtributo();
	private String nombreConReferencia = "";
	
	public ManagerEntidad(){

	}
	
	public NuevaEntidadDialogo getVistaNuevaEntidad() {
		return vistaNuevaEntidad;
	}

	public void setVistaNuevaEntidad(NuevaEntidadDialogo vistaNuevaEntidad, Proyecto proyecto, Diagrama diagramaEnPantalla) {
		this.vistaNuevaEntidad = vistaNuevaEntidad;
		this.proyecto = proyecto;
		this.diagramaActual = diagramaEnPantalla;
	}

	public GlobalEntidadDialogo getVistaEntidadGlobal() {
		return vistaEntidadGlobal;
	}

	public void setVistaEntidadGlobal(GlobalEntidadDialogo vistaEntidadGlobal, Proyecto proyecto, Diagrama diagramaEnPantalla) {
		this.vistaEntidadGlobal = vistaEntidadGlobal;
		this.proyecto = proyecto;
		this.diagramaActual = diagramaEnPantalla;
	}
	
	public EditarEntidadDialogo getVistaEditarEntidad() {
		return vistaEditarEntidad;
	}

	public void setVistaEditarEntidad(EditarEntidadDialogo vistaEditarEntidad, Proyecto proyecto, Diagrama diagramaEnPantalla) {
		this.vistaEditarEntidad = vistaEditarEntidad;
		this.proyecto = proyecto;
		this.diagramaActual = diagramaEnPantalla;
	}


	public EditarAtributoCompuestoDialogo getVistaAtributoCompuesto() {
		return vistaAtributoCompuesto;
	}

	public void setVistaAtributoCompuesto(
			EditarAtributoCompuestoDialogo vistaAtributoCompuesto,Proyecto proyecto, Diagrama diagramaEnPantalla) {
		this.vistaAtributoCompuesto = vistaAtributoCompuesto;
		this.proyecto = proyecto;
		this.diagramaActual = diagramaEnPantalla;
	}
	

	public void getListenerBotonNuevaEntidad() {
		try{
			boolean existeEntidad = false;
			String nombre = vistaNuevaEntidad.getNombreEntidad();
					    
			for(Entidad entidad: proyecto.getListaEntidades()){
				if(entidad.getNombre().equals(nombre)){
					existeEntidad = true;
				}
			}
			
			if (existeEntidad){
				JOptionPane.showMessageDialog(vistaNuevaEntidad, Mensaje.ENTIDAD_EXISTENTE,Mensaje.MENSAJE_ERROR,
	                    JOptionPane.INFORMATION_MESSAGE);
			}
			else{
				
				this.getListenerBotonAgregarEntidad();
			}
			}
			 catch (NullPointerException ex) {
				System.out.println("Error de null pointer");
			}
		
	}
	
	public void getListenerBotonAgregarEntidad() {
		modelEntidad = new Entidad(vistaNuevaEntidad.getNombreEntidad());
		modelEntidad.setTipo(vistaNuevaEntidad.getTipoEntidad());
		Coordenada coordenada = new Coordenada(20,60,30,modelEntidad.getNombre().length()*10,Entidad.class);
		Object entidad = controladorAreaDeTrabajo.dibujarEntidad(modelEntidad, coordenada);
		
		
		if(!vistaNuevaEntidad.getNombreAtributo().equals("")){
			
			nombreConReferencia = this.getReferenciaAlOrigenAlCrearElemento(); 
			
			if(vistaNuevaEntidad.getComposicion().equals("Compuesto")){
				
				
				
			
				modelAtributoCompuesto = new  AtributoCompuesto(vistaNuevaEntidad.getNombreAtributo(),
																	 vistaNuevaEntidad.getTipoAtributo(),
																	 vistaNuevaEntidad.getTipoDeDato(),
																	 vistaNuevaEntidad.getCardinalidad(),
																	 vistaNuevaEntidad.getComposicion(),
																	 vistaNuevaEntidad.getIdentificador());
		        
				modelEntidad.getListaAtributosCompuestos().add(modelAtributoCompuesto);
				
				Coordenada coordenadaAtributoCompuesto = new Coordenada(10,10,25,(modelAtributoCompuesto.getNombre().length() + modelAtributoCompuesto.getCardinalidad().length())*10,AtributoCompuesto.class);
				
				controladorAreaDeTrabajo.dibujarAtributoCompuesto(entidad, modelAtributoCompuesto, coordenadaAtributoCompuesto,nombreConReferencia);
			} 
			else if(vistaNuevaEntidad.getComposicion().equals("Simple")){
			
				//nombreConReferencia = this.getReferenciaAlOrigenAlCrearElemento(); 
				
				
				modelAtributo = new Atributo(vistaNuevaEntidad.getNombreAtributo(),
											  vistaNuevaEntidad.getTipoAtributo(),
											  vistaNuevaEntidad.getTipoDeDato(),
											  vistaNuevaEntidad.getCardinalidad(),
											  vistaNuevaEntidad.getComposicion(),
											  vistaNuevaEntidad.getIdentificador());
			    
				modelEntidad.getListaAtributos().add(modelAtributo);
				
				Coordenada coordenadaAtributo = new Coordenada(10,10,25,(modelAtributo.getNombre().length() + modelAtributo.getCardinalidad().length())*10,Atributo.class);
				
				controladorAreaDeTrabajo.dibujarAtributo(entidad, modelAtributo, coordenadaAtributo,nombreConReferencia);
		        
			}
		}
		
		
		
		proyecto.getListaEntidades().add(modelEntidad);
		diagramaActual.getListaEntidades().add(modelEntidad.getIdentificator());
		
		

	}

	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List<String> getEntidadesDelProyecto(){
		
		if (proyecto.getListaEntidades()!= null)
		{
			List<String> lista = new ArrayList<String>(); 
			
		    for(Entidad entidad: proyecto.getListaEntidades()){
		    	lista.add(entidad.getNombre());
		    }
		      Collections.sort(lista, new Comparator() {  
	        	  
		            public int compare(Object o1, Object o2) {  
		                String nombre1 = (String) o1;  
		                String nombre2 = (String) o2;  
		                return nombre1.compareToIgnoreCase(nombre2);  
		            }  
		        });  
		
		      return lista;
		}
		else return null;
	}

	public void agregarEntidadGlobal(String entidadElegida) {
		Entidad entidad = new Entidad();
		Iterator<Entidad> it = proyecto.getListaEntidades().iterator();
		boolean estado = false;
		while (estado == false){
			 entidad = (Entidad)it.next();
			 if (entidad.getIdentificator().equals(entidadElegida)){
				 modelEntidad = entidad;
				 estado = true;
			 }
		}
		
		diagramaActual.getListaEntidades().add(entidadElegida);
	
		Coordenada coordenada = new Coordenada(20,60,30,entidadElegida.length()*10,Entidad.class);
		
		Object entidadDibujada = controladorAreaDeTrabajo.dibujarEntidad(modelEntidad, coordenada);
		
		
		//dibujo los atributos de la entidad global
		dibujarAtributosSimples(modelEntidad.getListaAtributos(), entidadDibujada, nombreConReferencia);
		
		
		//dibujo los atributos compuestos de la entidad global
		dibujarAtributosCompuestos(modelEntidad.getListaAtributosCompuestos(), entidadDibujada, nombreConReferencia);
		
		
		//TODO falta dibujar para cada atributo compuesto, sus atributos y atributos compuestos que tengan, pensarlo
		//en forma recursiva
	}
	

	public void getListenerBotonAgregarAtributo(){
		//TODO: Ver que no llegue el nombre del atributo con la cardinalidad!, aplicar funcion quitarCardinalidadAlNombreDelAtributo.
		boolean atributoExistente = false;
        //Si el atributo que esta ingresando existe entonces emito un mensaje de error.				    
		for(Entidad entidad: proyecto.getListaEntidades()){
			if(entidad.getNombre().equals(vistaEditarEntidad.getNombreEntidad())){
				for (Atributo atributo: entidad.getListaAtributos()){
					  if (atributo.getNombre().equals(vistaEditarEntidad.getNombreAtributo()))
						  atributoExistente = true;
				   }
				for (AtributoCompuesto atributoCompuesto: entidad.getListaAtributosCompuestos()){
					  if (atributoCompuesto.getNombre().equals(vistaEditarEntidad.getNombreAtributo()))
						  atributoExistente = true;
				   }
			
				}
			}
		
		if (atributoExistente){
			JOptionPane.showMessageDialog(vistaEditarEntidad, Mensaje.ATRIBUTO_EXISTENTE,Mensaje.MENSAJE_ERROR,
                    JOptionPane.INFORMATION_MESSAGE);
		}
		else {
		
			Entidad modelEntidad = new Entidad("");
			for(Entidad entidad: proyecto.getListaEntidades()){
					 if (entidad.getIdentificator().equals(vistaEditarEntidad.getNombreEntidad())){
						 modelEntidad = entidad;
					 }
				}
			
			Object entidad = pantalla.getAreaDeTrabajo().getGraphComponent().getGraph().getSelectionCell();
			
						
			if(!vistaEditarEntidad.getNombreAtributo().equals("")){
				
				nombreConReferencia = this.getReferenciaAlOrigenAlEditarElemento(); 
			
			
				if(vistaEditarEntidad.getComposicion().equals("Compuesto")){
				
					modelAtributoCompuesto = new  AtributoCompuesto( vistaEditarEntidad.getNombreAtributo(),
																		  vistaEditarEntidad.getTipoAtributo(),
																		  vistaEditarEntidad.getTipoDeDato(),
																		  vistaEditarEntidad.getCardinalidad(),
																		  vistaEditarEntidad.getComposicion(),
																		  vistaEditarEntidad.getIdentificador());
		        
					modelEntidad.getListaAtributosCompuestos().add(modelAtributoCompuesto);
				
					Coordenada coordenadaAtributoCompuesto = new Coordenada(10,10,25,(modelAtributoCompuesto.getNombre().length() + modelAtributoCompuesto.getCardinalidad().length())*10,AtributoCompuesto.class);
				
					controladorAreaDeTrabajo.dibujarAtributoCompuesto(entidad, modelAtributoCompuesto, coordenadaAtributoCompuesto,nombreConReferencia);
				} 
				else if(vistaEditarEntidad.getComposicion().equals("Simple")){
				
					modelAtributo = new Atributo( vistaEditarEntidad.getNombreAtributo(),
												   vistaEditarEntidad.getTipoAtributo(),
												   vistaEditarEntidad.getTipoDeDato(),
												   vistaEditarEntidad.getCardinalidad(),
												   vistaEditarEntidad.getComposicion(),
												   vistaEditarEntidad.getIdentificador());
			    
				modelEntidad.getListaAtributos().add(modelAtributo);
				
				Coordenada coordenadaAtributo = new Coordenada(10,10,25,(modelAtributo.getNombre().length() + modelAtributo.getCardinalidad().length())*10,Atributo.class);
				
				controladorAreaDeTrabajo.dibujarAtributo(entidad, modelAtributo, coordenadaAtributo,nombreConReferencia);
		        
//				controladorDeAtributo.setEntidad(modelEntidad);
			   }
			}
		}
	}

	@Override
	public String getReferenciaAlOrigenAlEditarElemento() {
		return nombreConReferencia = DiagramaConstants.ENTIDAD + ":" + vistaEditarEntidad.getNombreEntidad() + "." +
		  vistaEditarEntidad.getComposicion() + ":" + vistaEditarEntidad.getNombreAtributo(); 
	}

	@Override
	public String getReferenciaAlOrigenAlCrearElemento() {
		return nombreConReferencia = DiagramaConstants.ENTIDAD + ":" + vistaNuevaEntidad.getNombreEntidad() + "." +
		vistaNuevaEntidad.getComposicion() + ":" + vistaNuevaEntidad.getNombreAtributo();
	}

	
	public int getCantEntidadesDiagramaActual(){
		return this.diagramaActual.getListaEntidades().size();
	}
	
	public boolean existeEntidadEnDiagramaActual(String entidad){
		return diagramaActual.getListaEntidades().contains(entidad);
	}
	
	private void dibujarAtributosSimples(List<Atributo> listaAtributos,Object entPadre, String nombrePadre) {
		
		int posicionX = 0;
		
		for (Atributo atributo : listaAtributos) {
			//TODO: Refactorizar, es por el ejemplo que no tiene cardinalidad inicalizada y emite un null pointer.
			if (atributo.getCardinalidad() == null){
				atributo.setCardinalidad("");
			}
			Coordenada coordenadaAtributo = new Coordenada(10 + posicionX,10,30,(atributo.getNombre().length() +
					atributo.getCardinalidad().length())*10,Atributo.class);
			controladorAreaDeTrabajo.dibujarAtributo(entPadre, atributo, coordenadaAtributo,nombrePadre);
			posicionX += 20;
		}
		
	}
	
	
	private void dibujarAtributosCompuestos(List<AtributoCompuesto> listaCompuestos,Object entPadre, String nombrePadre) {
			
		int posicionX = 0;
		
		for (AtributoCompuesto atributoComp : listaCompuestos) {
			
			Coordenada coordenadaAtributoCompuesto = new Coordenada(10 + posicionX,10,30,(atributoComp.getNombre().length() + atributoComp.getCardinalidad().length())*10,AtributoCompuesto.class);
			
			Object atCompDibujado = controladorAreaDeTrabajo.dibujarAtributoCompuesto(entPadre, atributoComp, coordenadaAtributoCompuesto,nombrePadre);
						
			//hace las llamadas recursivas
			String nombreConReferenciaParametro = nombrePadre+ "." +"Compuesto"+":"+atributoComp.getNombre();
			dibujarAtributosSimples(atributoComp.getListaAtributos(), atCompDibujado, nombreConReferenciaParametro);
			dibujarAtributosCompuestos(atributoComp.getListaAtributosCompuestos(), atCompDibujado, nombreConReferenciaParametro);
			
			posicionX += 30;
		}
	}

	

}
